<template>
  <!-- visible控制显示和隐藏 -->
  <!-- close事件：
          当关闭时调用
          点`x`或者点背后的阴影都会触发关闭
   -->
  <el-dialog :title="title" :visible="showDialog" @close="close">
    <el-form ref="form" :model="form" :rules="rules">
      <el-form-item label="部门名称" :label-width="formLabelWidth" prop="name">
        <el-input v-model="form.name" autocomplete="off" />
      </el-form-item>
      <el-form-item label="部门编码" :label-width="formLabelWidth" prop="code">
        <el-input v-model="form.code" autocomplete="off" />
      </el-form-item>
      <el-form-item
        label="活动负责人"
        :label-width="formLabelWidth"
        prop="manager"
      >
        <el-select
          v-model="form.manager"
          style="width: 100%"
          placeholder="请选择负责人"
          @focus="getEmpList"
        >
          <!-- label是显示的文字 -->
          <!-- value是它选择后的取的值 -->
          <el-option
            v-for="item in empList"
            :key="item.id"
            :label="item.username"
            :value="item.username"
          />
        </el-select>
      </el-form-item>
      <el-form-item
        label="部门介绍"
        :label-width="formLabelWidth"
        prop="introduce"
      >
        <el-input
          v-model="form.introduce"
          type="textarea"
          :rows="3"
          placeholder="请输入部门介绍"
          resize="none"
        />
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="close">取 消</el-button>
      <el-button type="primary" @click="save">确 定</el-button>
    </div>
  </el-dialog>
</template>

<script>
// 导入接口
import { getDepts, addDepts, deptsDetail, editDepts } from '@/api/departments'
import { getEmpSimple } from '@/api/employees'
export default {
  props: {
    // 接收父组件传递过来的显示和隐藏
    showDialog: {
      type: Boolean,
      required: true
    },

    // 接收父id
    pid: {
      type: String,
      required: true
    }
  },
  data() {
    // 检查部门名是否重复的自定义函数
    const checkName = async(rule, value, callback) => {
      // 1. 发请求获取最新的部门列表
      const res = await getDepts()
      // 如果是修改就找同级的
      if (this.form.id) {
        // 修改是找同级里是否有同名的，所以先找出所有同级的部门
        // 注意：这里是要找同级里除了自己以外的
        // 因为：我们的名字允许跟以前一样，但不允许跟同级其他的一样
        const list = res.data.depts.filter(
          (v) => v.pid === this.form.pid && v.name != this.oldForm.name
        )
        // 要不要找我输入的名字在同级里一致
        const result = list.find((v) => v.name === value)

        if (result) {
          // 找到了代表我输入的名字已经存在过了
          callback(new Error('部门名称不能重复'))
        } else {
          callback()
        }
      } else {
        // 如果是新增就找子节点有没有重复
        // 2. 再根据被点的部门id，去找到它里面的子节点： pid  === 被点的自己id（本项目中就是this.pid）
        const children = res.data.depts.filter((v) => v.pid === this.pid)
        // 3. 判断输入的内容在不在数组里面
        const result = children.find((v) => v.name === value)
        if (result) {
          // 代表找到了，找到了就有重复的
          callback(new Error('部门名称不能重复'))
        } else {
          // 没找到就代表这个名字可以用，就通过
          callback()
        }
      }
    }

    // 检查部门代码是否重复
    const checkCode = async(rule, value, callback) => {
      // 如果是修改状态，且我现在输入的code跟之前输入的code一样，直接通过
      if (this.form.id && this.oldForm.code === value) {
        return callback()
      }

      // 能来到这，只能证明我输入的code已经不是原本的code，那就得去全部数组里判断有没有重复的
      // 查出最新的部门列表
      const res = await getDepts()
      // 直接判断输入的编码在不在所有的部门列表里面
      const result = res.data.depts.find((v) => v.code === value)
      if (result) {
        // 代表找到了，找到了就有重复的
        callback(new Error('部门编码不能重复'))
      } else {
        // 没找到就代表这个名字可以用，就通过
        callback()
      }
    }

    return {
      // 左侧文字宽度
      formLabelWidth: '120px',
      // 专门用来保存旧名字
      oldForm: {},
      // 跟表单绑定的对象
      form: {},
      // 规则对象
      rules: {
        name: [
          { required: true, message: '请输入部门名称', trigger: 'blur' },
          { min: 1, max: 50, message: '名称在1-50之间', trigger: 'blur' },
          // 使用自定义校验规则
          { validator: checkName, trigger: 'blur' }
        ],
        code: [
          { required: true, message: '请输入部门编码', trigger: 'blur' },
          { min: 1, max: 50, message: '编码在1-50之间', trigger: 'blur' },
          { validator: checkCode, trigger: 'blur' }
        ],

        manager: [{ required: true, message: '请选择负责人', trigger: 'blur' }],

        introduce: [
          { required: true, message: '请输入部门介绍', trigger: 'blur' },
          { min: 1, max: 300, message: '编码在1-300之间', trigger: 'blur' }
        ]
      },

      // 保存员工列表的数组
      empList: []
    }
  },

  computed: {
    title() {
      // 有id叫查看部门，没id叫新增部门
      return this.form.id ? '查看部门' : '新增部门'
    }
  },

  methods: {
    // 用来根据id获取部门详情的方法
    async getDetail(id) {
      // 这里到时候要传递一个id
      const res = await deptsDetail(id)
      // 给form就能显示到界面
      this.form = res.data

      // 马上把这个名字存到oldForm
      this.oldForm.name = this.form.name
      this.oldForm.code = this.form.code
    },

    // 关闭事件
    close() {
      // 因为resetFields只能清空表单里的内容，那如果有别的内容不会清空
      // 所以我们要手动把form里的内容清空
      this.form = {}
      // 清空表单里输入的内容(去element-ui找线索)
      // 重置为初始值(初始值就是一开始的值)
      this.$refs.form.resetFields()

      // 想改showDialog改成false，但是又不能直接改，所以子传父
      this.$emit('update:showDialog', false)
    },

    // 下拉框获得焦点事件
    async getEmpList() {
      const res = await getEmpSimple()
      this.empList = res.data
    },

    // 点击确定的点击事件
    save() {
      // 做整个表单验证
      this.$refs.form.validate(async(v) => {
        if (v) {
          let res = null

          if (this.form.id) {
            // 做修改
            res = await editDepts(this.form)
          } else {
            // 这样写的意思是传递一个对象，这个对象里既有form的四个属性又有pid
            res = await addDepts({
              ...this.form,
              pid: this.pid
            })
          }

          if (res.code === 10000) {
            // 弹出服务器消息
            this.$message.success(res.message)
            this.close()
            // 最好是要保持最新的数据,通知父组件刷新
            this.$emit('reload')
          } else {
            // 把服务器失败信息弹出
            this.$message.error(res.message)
          }
        }
      })
    }
  }
}
</script>

<style>
</style>
